package com.inspur.edp.formserver.vmmanager.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.json.Variable.CommonVariableDeserializer;
import com.inspur.edp.cef.designtime.api.json.Variable.CommonVariableSerializer;
import com.inspur.edp.cef.designtime.api.variable.CommonVariable;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.util.UpdateVoVariableUtil;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

public class UpdateVariableWithUdtService {
    private String errorCode = "UpdateVariableWithUdtService";

    public static UpdateVariableWithUdtService getInstance() {

        return new UpdateVariableWithUdtService();
    }

    /**
     * 根据选中的udt元数据,更新多值udt字段信息
     * 更新ChildElements,Mapping
     * 说明：若为字段上选择udt，所有属性带出；若为加载更新，则仅更新使用方式为【约束】的属性。
     *
     * @return 更新后字段的json序列化
     */
    public String updateVariableWithRefUdt(String refUdtId, String path, String udtElementJson, boolean isFirstChoose) {
        RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);

        GspMetadata refUdtMetadata = metadataService.getRefMetadata(refUdtId);

        CommonVariable commonVariable;
        try {
            commonVariable = getMapper().readValue(udtElementJson, CommonVariable.class);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0041, e);
        }

        IMetadataContent content = refUdtMetadata.getContent();
        if (content instanceof UnifiedDataTypeDef) {
            UpdateVoVariableUtil util = new UpdateVoVariableUtil();
            util.UpdateElementWithRefUdt(commonVariable, (UnifiedDataTypeDef) content, isFirstChoose);
        } else {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0042, null);
        }

        String eleJson;
        try {
            eleJson = getMapper().writeValueAsString(commonVariable);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0043, e);
        }
        return eleJson;
    }

    public String updateVariableWithRefUdt(JsonNode node, String refUdtId, String path, String udtElementJson, boolean isFirstChoose) {

        GspMetadata refUdtMetadata = WebControllerService.getMetadata(node, path, "", refUdtId);
        CommonVariable commonVariable;
        try {
            commonVariable = getMapper().readValue(udtElementJson, CommonVariable.class);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0041, e);
        }

        IMetadataContent content = refUdtMetadata.getContent();
        if (content instanceof UnifiedDataTypeDef) {
            UpdateVoVariableUtil util = new UpdateVoVariableUtil();
            util.UpdateElementWithRefUdt(commonVariable, (UnifiedDataTypeDef) content, isFirstChoose);
        } else {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0042, null);
        }

        String eleJson;
        try {
            eleJson = getMapper().writeValueAsString(commonVariable);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0043, e);
        }
        return eleJson;
    }

    private ObjectMapper getMapper() {

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(IGspCommonField.class, new CommonVariableDeserializer());
        module.addSerializer(IGspCommonField.class, new CommonVariableSerializer());
        mapper.registerModule(module);
        return mapper;
    }
}
